package vip.xiaonuo.megvii.service;


import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.joe.util.GsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.core.file.modular.local.LocalFileOperator;
import vip.xiaonuo.core.pojo.response.ErrorResponseData;
import vip.xiaonuo.core.pojo.response.ResponseData;
import vip.xiaonuo.core.pojo.response.SuccessResponseData;
import vip.xiaonuo.digest.DigestHttpClient;
import vip.xiaonuo.digest.DigestHttpUtil;
import vip.xiaonuo.digest.HttpRequestWithFile;
import vip.xiaonuo.facedoor.modular.memberfeatures.entity.MemberFeatures;
import vip.xiaonuo.facedoor.modular.memberfeatures.param.MemberFeaturesParam;
import vip.xiaonuo.facedoor.modular.memberfeatures.service.MemberFeaturesService;
import vip.xiaonuo.facedoor.modular.memberuser.entity.MemberUser;
import vip.xiaonuo.megvii.BaseConfig;
import vip.xiaonuo.megvii.config.model.ApiResponse;
import vip.xiaonuo.megvii.faces.FaceCodeDefinition;
import vip.xiaonuo.megvii.faces.model.FaceDelete;
import vip.xiaonuo.megvii.faces.model.FaceInfo;
import vip.xiaonuo.megvii.service.query.DeviceMegviiQueryService;
import vip.xiaonuo.modular.devicemegvii.entity.DeviceMegvii;
import vip.xiaonuo.modular.devicemegvii.service.DeviceMegviiService;
import vip.xiaonuo.modular.facegroupfacetokenrela.entity.FacegroupFacetokenRela;
import vip.xiaonuo.modular.facegroupfacetokenrela.param.FaceGroupFaceTokenRelaSave;
import vip.xiaonuo.modular.facegroupfacetokenrela.param.FacegroupFacetokenRelaParam;
import vip.xiaonuo.modular.facegroupfacetokenrela.service.FacegroupFacetokenRelaService;
import vip.xiaonuo.sys.config.FileConfig;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import vip.xiaonuo.facedoor.modular.device.entity.DeviceCategory;

@Service
@Slf4j
public class DeviceMegviiFaceService {

    @Resource
    private MemberFeaturesService memberFeaturesService;

    @Resource
    private FileConfig fConfig;

    @Resource
    private DeviceMegviiQueryService queryService;

    @Resource
    private DeviceMegviiService megviiService ;

    @Resource
    private FacegroupFacetokenRelaService relationService;

    @Resource
    private MemberFeaturesService featuresService;


    /**
     * @param user
     * @return
     */
    public ResponseData faceInStore(MemberUser user) {
        if(user==null){
            return new ErrorResponseData(-1,"业务数据不存在");
        }else if(user.getPhoto()==null || "".equals(user.getPhoto())){
            return new ErrorResponseData(-1,"请先上传人脸图片,再入库");
        }
        LocalFileOperator operator = (LocalFileOperator)fConfig.fileOperator();
        String basePath = operator.getCurrentSavePath() + File.separator + fConfig.DEFAULT_BUCKET;
        String fileLocation = basePath + "" + user.getPhoto();
        log.info("人脸照片位置：{}",fileLocation);
        if(!FileUtil.exist(fileLocation)){
            return new ErrorResponseData(-1,"人脸照片不存在，请重新上传");
        }

        File f = new File(fileLocation);
        // 当前用户关联的AI设备
        List<DeviceMegvii> devices = queryService.getDeviceByUser(user);

        if(devices == null || devices.size() ==0 ){
            return new ErrorResponseData(-1,"没找到可用的AI智能分析盒");
        }
        int successNum = 0;
        int continueNum = 0;
        int failNum = 0;
        String remark = "";
        for (DeviceMegvii device : devices){
            ApiResponse response = this.doFaceInStore(f,device);
            log.info("请求结果：{}",JSON.toJSONString(response));
            // 判断请求结果,后续业务处理
            if( response.isSuccess()){
                try{
                    JSONObject obj = (JSONObject) response.getData();
                    FaceInfo face = JSON.parseObject(obj.toJSONString(), FaceInfo.class );
                    MemberFeatures feature = new MemberFeatures();
                    feature.setType(0);
                    feature.setDwMemberUserId(user.getId());
                    feature.setDeviceId(device.getDeviceId());
                    feature.setBizDeviceId(device.getId());
                    feature.setDeviceName(device.getMachName());
                    feature.setPlatform(DeviceCategory.SUB_TYPE_BOX);
                    feature.setImageId(face.getImageId());
                    feature.setFaceToken(face.getFaceToken());
                    feature.setValue(face.getFaceToken());
                    memberFeaturesService.save(feature);
                    successNum ++;
                }catch (Exception e){
                    e.printStackTrace();
                    failNum ++;
                }
            }else {
                int code = response.getCode();
                if(code == FaceCodeDefinition._code_104204 ){
                    continueNum ++;
                    remark += "跳过原因：" + FaceCodeDefinition.getMessage(code);
                }else{
                    failNum ++;
                    remark += "失败原因：" + FaceCodeDefinition.getMessage(code);
                }
            }
        }
        String msg = "总计待入库数量:" + devices.size();

        msg += successNum>0 ? ",成功"+ successNum +"个" : "";
        msg += continueNum>0 ? ",跳过"+ continueNum + "个" : "";
        msg += failNum>0 ? ",失败"+ failNum + "个" : "";

        msg += "。"+ remark;

        boolean success = successNum>0 || failNum==0;

        return new ResponseData(success,0,msg,null);
    }

    /**
     * 操作人脸入库
     * @param f
     * @param device
     * @return
     */
    private ApiResponse doFaceInStore(File f,DeviceMegvii device){
        String url = DeviceMegviiBaseService.getMachAddress(device);
        if(url==null || url.length()==0){
            return ApiResponse.failed(-1,"参数不完整,请检查");
        }
        HttpClient client = DigestHttpClient.getDigestHttpClient(device);

        url += BaseConfig.URL_FACES;
        Map<String,File> map = new HashMap<>();
        map.put("image",f);

        String result = HttpRequestWithFile.sendPost(client,url,map,null);
        return JSON.parseObject(result,ApiResponse.class);
    }

    public ResponseData faceDelete(FaceDelete faceDelete) {
        int deleteMode = faceDelete.getDeleteMode();
        if(deleteMode == 0 ){ // 删除人脸
            return this.doDeleteFace(faceDelete);
        }else if(deleteMode == 1){ // 删除原图
            return this.doDeleteFaceImage(faceDelete);
        }else {
            return ErrorResponseData.error(-1,"未知删除类型");
        }

    }

    /**
     * 删除人脸
     * @param faceDelete
     * @return
     */
    private ResponseData doDeleteFace(FaceDelete faceDelete) {
        DeviceMegvii device = megviiService.getById(faceDelete.getBizDeviceId());
        if(device==null || device.getDelFlag()==1 ){
            return ErrorResponseData.error(-1,"特征值对应的设备不存在");
        }

        String url = DeviceMegviiBaseService.getMachAddress(device);
        if(url==null || url.length()==0){
            return ErrorResponseData.error(-1,"参数不完整,请检查参数配置");
        }

        HttpClient client = DigestHttpClient.getDigestHttpClient(device);
        String requestUrl = url + BaseConfig.URL_FACE_TOKEN_DELETE.replace("{faceToken}",faceDelete.getFaceToken());
        ApiResponse resp = DigestHttpUtil.sendDelete(client,requestUrl , "");
        log.info("人脸删除返回：{}" , GsonUtils.objToJson(resp));
        int code = resp.getCode();
        if(code == 0 || code == 104202){ // 人脸删除成功 104202 对应人脸不存在，可能情况：AI后台已删除，本地未同步，所以本地也需要删除相关业务数据
            this.doDeleteFaceInDB(faceDelete.getId(),faceDelete.getDeleteMode());
            return SuccessResponseData.success();
        }else {
            return ErrorResponseData.error(code, FaceCodeDefinition.getMessage(code));
        }
    }



    /**
     * 删除原图
     * @param faceDelete
     * @return
     */
    private ResponseData doDeleteFaceImage(FaceDelete faceDelete) {
        DeviceMegvii device = megviiService.getById(faceDelete.getBizDeviceId());
        if(device==null || device.getDelFlag()==1 ){
            return ErrorResponseData.error(-1,"特征值对应的设备不存在");
        }

        String url = DeviceMegviiBaseService.getMachAddress(device);
        if(url==null || url.length()==0){
            return ErrorResponseData.error(-1,"参数不完整,请检查参数配置");
        }

        HttpClient client = DigestHttpClient.getDigestHttpClient(device);
        String requestUrl = url + BaseConfig.URL_FACE_IMAGE_DELETE.replace("{imageId}",faceDelete.getImageId());
        ApiResponse resp = DigestHttpUtil.sendDelete(client,requestUrl , "");
        log.info("人脸原图删除返回：{}" , GsonUtils.objToJson(resp));
        int code = resp.getCode();
        if(code == 0 || code == 104203){ // 人脸原图删除成功 104203 对应人脸原图不存在，可能情况：AI后台已删除，本地未同步，所以本地也需要删除相关业务数据

            this.doDeleteFaceInDB(faceDelete.getId(),faceDelete.getDeleteMode());
            return SuccessResponseData.success();
        }else {
            return ErrorResponseData.error(code, FaceCodeDefinition.getMessage(code));
        }
    }

    /**
     * 从数据库删除关联数据
     * @param id    特征值对应的ID
     * @param mode  删除模式(删除原图时，需要删除特征值数据)
     */
    @Transactional(rollbackFor = Exception.class)
    protected void doDeleteFaceInDB(Long id,int mode) {
        FacegroupFacetokenRelaParam param = new FacegroupFacetokenRelaParam();
        param.setFeaturesId(id);
        List<FacegroupFacetokenRela> relates = relationService.list(param);
        relationService.removeBatchByIds(relates);
        //原图删除模式
        if(mode==1){
            memberFeaturesService.removeById(id);
        }
    }
}
